@@ -11,7 +11,7 @@ module Agents |
||
| 11 | 11 |
description <<-MD |
| 12 | 12 |
The Shell Command Agent will execute commands on your local system, returning the output. |
| 13 | 13 |
|
| 14 |
- `command` specifies the command (either a shell command line string or an array of command line arguments) to be executed, and `path` will tell ShellCommandAgent in what directory to run this command. |
|
| 14 |
+ `command` specifies the command (either a shell command line string or an array of command line arguments) to be executed, and `path` will tell ShellCommandAgent in what directory to run this command. The content of `stdin` will be fed to the command via the standard input. |
|
| 15 | 15 |
|
| 16 | 16 |
`expected_update_period_in_days` is used to determine if the Agent is working. |
| 17 | 17 |
|
@@ -50,6 +50,12 @@ module Agents |
||
| 50 | 50 |
errors.add(:base, "The path, command, and expected_update_period_in_days fields are all required.") |
| 51 | 51 |
end |
| 52 | 52 |
|
| 53 |
+ case options['stdin'] |
|
| 54 |
+ when String, nil |
|
| 55 |
+ else |
|
| 56 |
+ errors.add(:base, "stdin must be a string.") |
|
| 57 |
+ end |
|
| 58 |
+ |
|
| 53 | 59 |
unless Array(options['command']).all? { |o| o.is_a?(String) }
|
| 54 | 60 |
errors.add(:base, "command must be a shell command line string or an array of command line arguments.") |
| 55 | 61 |
end |
@@ -79,8 +85,9 @@ module Agents |
||
| 79 | 85 |
if Agents::ShellCommandAgent.should_run? |
| 80 | 86 |
command = opts['command'] |
| 81 | 87 |
path = opts['path'] |
| 88 |
+ stdin = opts['stdin'] |
|
| 82 | 89 |
|
| 83 |
- result, errors, exit_status = run_command(path, command) |
|
| 90 |
+ result, errors, exit_status = run_command(path, command, stdin) |
|
| 84 | 91 |
|
| 85 | 92 |
vals = {"command" => command, "path" => path, "exit_status" => exit_status, "errors" => errors, "output" => result}
|
| 86 | 93 |
created_event = create_event :payload => vals |
@@ -91,15 +98,22 @@ module Agents |
||
| 91 | 98 |
end |
| 92 | 99 |
end |
| 93 | 100 |
|
| 94 |
- def run_command(path, command) |
|
| 101 |
+ def run_command(path, command, stdin) |
|
| 95 | 102 |
begin |
| 96 | 103 |
rout, wout = IO.pipe |
| 97 | 104 |
rerr, werr = IO.pipe |
| 105 |
+ rin, win = IO.pipe |
|
| 98 | 106 |
|
| 99 |
- pid = spawn(*command, chdir: path, out: wout, err: werr) |
|
| 107 |
+ pid = spawn(*command, chdir: path, out: wout, err: werr, in: rin) |
|
| 100 | 108 |
|
| 101 | 109 |
wout.close |
| 102 | 110 |
werr.close |
| 111 |
+ rin.close |
|
| 112 |
+ |
|
| 113 |
+ if stdin |
|
| 114 |
+ win.write stdin |
|
| 115 |
+ win.close |
|
| 116 |
+ end |
|
| 103 | 117 |
|
| 104 | 118 |
(result = rout.read).strip! |
| 105 | 119 |
(errors = rerr.read).strip! |
@@ -12,7 +12,8 @@ describe Agents::ShellCommandAgent do |
||
| 12 | 12 |
|
| 13 | 13 |
@valid_params2 = {
|
| 14 | 14 |
path: @valid_path, |
| 15 |
- command: [RbConfig.ruby, '-e', 'puts "hello, world."; STDERR.puts "warning!"'], |
|
| 15 |
+ command: [RbConfig.ruby, '-e', 'puts "hello, #{STDIN.eof? ? "world" : STDIN.read.strip}."; STDERR.puts "warning!"'],
|
|
| 16 |
+ stdin: "{{name}}",
|
|
| 16 | 17 |
expected_update_period_in_days: '1', |
| 17 | 18 |
} |
| 18 | 19 |
|
@@ -27,7 +28,8 @@ describe Agents::ShellCommandAgent do |
||
| 27 | 28 |
@event = Event.new |
| 28 | 29 |
@event.agent = agents(:jane_weather_agent) |
| 29 | 30 |
@event.payload = {
|
| 30 |
- :cmd => "ls" |
|
| 31 |
+ 'name' => 'Huginn', |
|
| 32 |
+ 'cmd' => 'ls', |
|
| 31 | 33 |
} |
| 32 | 34 |
@event.save! |
| 33 | 35 |
|
@@ -58,7 +60,7 @@ describe Agents::ShellCommandAgent do |
||
| 58 | 60 |
|
| 59 | 61 |
describe "#working?" do |
| 60 | 62 |
it "generating events as scheduled" do |
| 61 |
- stub(@checker).run_command(@valid_path, 'pwd') { ["fake pwd output", "", 0] }
|
|
| 63 |
+ stub(@checker).run_command(@valid_path, 'pwd', nil) { ["fake pwd output", "", 0] }
|
|
| 62 | 64 |
|
| 63 | 65 |
expect(@checker).not_to be_working |
| 64 | 66 |
@checker.check |
@@ -71,7 +73,7 @@ describe Agents::ShellCommandAgent do |
||
| 71 | 73 |
|
| 72 | 74 |
describe "#check" do |
| 73 | 75 |
before do |
| 74 |
- stub(@checker).run_command(@valid_path, 'pwd') { ["fake pwd output", "", 0] }
|
|
| 76 |
+ stub(@checker).run_command(@valid_path, 'pwd', nil) { ["fake pwd output", "", 0] }
|
|
| 75 | 77 |
end |
| 76 | 78 |
|
| 77 | 79 |
it "should create an event when checking" do |
@@ -84,7 +86,7 @@ describe Agents::ShellCommandAgent do |
||
| 84 | 86 |
it "should create an event when checking (unstubbed)" do |
| 85 | 87 |
expect { @checker2.check }.to change { Event.count }.by(1)
|
| 86 | 88 |
expect(Event.last.payload[:path]).to eq(@valid_path) |
| 87 |
- expect(Event.last.payload[:command]).to eq([RbConfig.ruby, '-e', 'puts "hello, world."; STDERR.puts "warning!"']) |
|
| 89 |
+ expect(Event.last.payload[:command]).to eq([RbConfig.ruby, '-e', 'puts "hello, #{STDIN.eof? ? "world" : STDIN.read.strip}."; STDERR.puts "warning!"'])
|
|
| 88 | 90 |
expect(Event.last.payload[:output]).to eq('hello, world.')
|
| 89 | 91 |
expect(Event.last.payload[:errors]).to eq('warning!')
|
| 90 | 92 |
end |
@@ -97,7 +99,7 @@ describe Agents::ShellCommandAgent do |
||
| 97 | 99 |
|
| 98 | 100 |
describe "#receive" do |
| 99 | 101 |
before do |
| 100 |
- stub(@checker).run_command(@valid_path, @event.payload[:cmd]) { ["fake ls output", "", 0] }
|
|
| 102 |
+ stub(@checker).run_command(@valid_path, @event.payload[:cmd], nil) { ["fake ls output", "", 0] }
|
|
| 101 | 103 |
end |
| 102 | 104 |
|
| 103 | 105 |
it "creates events" do |
@@ -108,6 +110,13 @@ describe Agents::ShellCommandAgent do |
||
| 108 | 110 |
expect(Event.last.payload[:output]).to eq("fake ls output")
|
| 109 | 111 |
end |
| 110 | 112 |
|
| 113 |
+ it "creates events (unstubbed)" do |
|
| 114 |
+ @checker2.receive([@event]) |
|
| 115 |
+ expect(Event.last.payload[:path]).to eq(@valid_path) |
|
| 116 |
+ expect(Event.last.payload[:output]).to eq('hello, Huginn.')
|
|
| 117 |
+ expect(Event.last.payload[:errors]).to eq('warning!')
|
|
| 118 |
+ end |
|
| 119 |
+ |
|
| 111 | 120 |
it "does not run when should_run? is false" do |
| 112 | 121 |
stub(Agents::ShellCommandAgent).should_run? { false }
|
| 113 | 122 |
|